// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.1

package menu

import (
	"audio-server/internal/model"
	"audio-server/internal/sqlutil"
	"audio-server/internal/svc"
	"audio-server/internal/types"
	"context"
	"database/sql"
	"encoding/json"
	"strconv"

	"github.com/zeromicro/go-zero/core/logx"
)

type MenuLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MenuLogic {
	return &MenuLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func nullInt64ToInt(nullInt sql.NullInt64) int {
	if nullInt.Valid {
		return int(nullInt.Int64)
	}
	return 0
}

func nullStringToString(nullString sql.NullString) string {
	if nullString.Valid {
		return nullString.String
	}
	return ""
}

func (l *MenuLogic) Menu() (resp []types.UserMenuRes, err error) {
	userId, _ := l.ctx.Value("userId").(json.Number).Int64()
	menuModel := model.NewMenuModel(l.svcCtx.Conn)
	usersModel := model.NewUsersModel(l.svcCtx.Conn)
	user, err := usersModel.FindById(l.ctx, userId)
	if err != nil {
		return nil, err
	}
	ids := user.RoleIds
	if len(ids) == 0 {
		return []types.UserMenuRes{}, nil
	}
	rolesModel := model.NewSysRoleModel(l.svcCtx.Conn)
	roles, err := rolesModel.FindRoleByIds(l.ctx, ids)
	if err != nil {
		return nil, err
	}
	// 解析 roles 中的 MenuIds
	var allMenuIds []int64
	var isAdmin bool
	for _, role := range roles {
		var menuIdStrs []string
		var menuIds []int64
		isAdmin = role.IsAdmin == 1
		roleMenuIds := sqlutil.NullStringToString(role.MenuIds)
		if len(roleMenuIds) > 0 {
			// 将 role.MenuIds 从 JSON 字符串解析为 int64 切片
			err := json.Unmarshal([]byte(roleMenuIds), &menuIdStrs)
			if err != nil {
				return nil, err
			}
			for _, idStr := range menuIdStrs {
				id, err := strconv.ParseInt(idStr, 10, 64)
				if err != nil {
					return nil, err
				}
				menuIds = append(menuIds, id)
			}
			// 合并到总菜单ID列表中
			allMenuIds = append(allMenuIds, menuIds...)
		}
	}

	menus, err := menuModel.FindUserMenu(l.ctx, allMenuIds, isAdmin)
	if err != nil {
		return nil, err
	}
	// 简单的切片转换
	var menuList []types.UserMenuRes
	for _, menu := range menus {
		menuList = append(menuList, types.UserMenuRes{
			MenuId:     int(menu.Id),
			ParentId:   nullInt64ToInt(menu.ParentId),
			Title:      nullStringToString(menu.Title),
			Path:       menu.Path,
			Component:  menu.Component,
			Redirect:   nullStringToString(menu.Redirect),
			Type:       nullInt64ToInt(menu.Type),
			SvgIcon:    nullStringToString(menu.SvgIcon),
			Icon:       nullStringToString(menu.Icon),
			KeepAlive:  int(menu.KeepAlive),
			Hidden:     nullInt64ToInt(menu.Hidden),
			Sort:       nullInt64ToInt(menu.Sort),
			ActiveMenu: nullStringToString(menu.ActiveMenu),
			Breadcrumb: nullInt64ToInt(menu.Breadcrumb),
			ShowInTabs: nullInt64ToInt(menu.ShowInTabs),
			AlwaysShow: nullInt64ToInt(menu.AlwaysShow),
			Affix:      nullInt64ToInt(menu.Affix),
		})
	}
	return l.buildMenuTree(menuList, 0), nil

}

func (l *MenuLogic) buildMenuTree(menus []types.UserMenuRes, parentId int) []types.UserMenuRes {
	var rootMenus []types.UserMenuRes
	for _, menu := range menus {
		if menu.ParentId == parentId {
			menu.Children = l.buildMenuTree(menus, menu.MenuId)
			rootMenus = append(rootMenus, menu)
		}
	}
	return rootMenus
}
